# -*- coding: utf-8 -*-
# @Author  : longbhu
# @Time    : 2025/5/21 11:15
# @Function:
import os
import re
import logging
import geopandas as gpd
import numpy as np
import pandas as pd
import rasterio
from tqdm import tqdm
from tif_stats import admin_code_to_name_default, get_excel_value_by_key
from typing import List, Optional
from calc_v1.tif_tools import dev_multiply_tif_data_by_factor, tif_mask_by_shapefile
from calc_v1.tif_tools.shp import extract_and_save_shapefile


# 定义常量
# GEP_RESULT_PATH = r'I:\GEP_result\test'
GEP_PROJECT_PATH = r'I:\GEP_project'
SHAPEFILE_PATH = r'E:\shp\2025购买边界shp2021\全国统计乡镇区划\全国统计乡镇界.shp'
# OUTPUT_FOLDER = r'H:\test\36\output'
EXCEL_PATH = r'H:\GEP_excel_data\V_price\价格表-总表.xlsx'

def rename_xiangCode_replace_provinceCode(root_folder):
    """
    遍历 root_folder 及其子文件夹，重命名所有 .tif 文件，
    将类似 '360000_Qsr_Qsr_replaced_output_361124100.tif' 的文件名
    改为 '361124100_Qsr_Qsr_replaced_output.tif'
    """

    for dirpath, _, filenames in os.walk(root_folder):
        for filename in filenames:
            if filename.lower().endswith('.tif'):
                old_path = os.path.join(dirpath, filename)

                # 使用正则提取前后数字部分
                match = re.match(r'^\d+_(.*?)(_\d+)(\.tif)$', filename, re.IGNORECASE)
                if match:
                    content_part = match.group(1)  # Qsr_Qsr_replaced_output
                    last_number = match.group(2)   # _361124100
                    ext = match.group(3)           # .tif

                    new_filename = f"{last_number[1:]}_{content_part}{ext}"  # 去掉开头的下划线
                    new_path = os.path.join(dirpath, new_filename)

                    print(f"Renaming:\n  {old_path}\n→ {new_path}")
                    os.rename(old_path, new_path)
                else:
                    print(f"未匹配到符合条件的文件名格式: {filename}")

def create_admin_code_mapping(shp_path):
    """
    从 shp 文件中读取 xiang_code 和 xiang_name 字段，构建行政区划代码与名称的映射字典。
    :param shp_path: .shp 文件路径
    :return: { "xiang_code": "xiang_name", ... }
    """
    # 读取 shp 文件
    gdf = gpd.read_file(shp_path)

    # 检查是否包含必要字段
    if 'xiang_code' not in gdf.columns or 'xiang_name' not in gdf.columns:
        raise KeyError("shp 文件必须包含 'xiang_code' 和 'xiang_name' 字段")

    # 构建字典
    admin_code_to_name = {
        str(row['xiang_code']): row['xiang_name'] for _, row in gdf.iterrows()
    }

    return admin_code_to_name


def analyze_tif_files_xiang(folder_path: str, excel_path: str, mapping_name: str,
                            admin_code_to_name=None, output_path: str = None) -> None:
    """
    分析指定文件夹中的 TIF 文件，并将结果保存到 Excel 文件中。根据tif文件名的信息，制作列名。

    :param folder_path: 包含 TIF 文件的文件夹路径
    :param admin_code_to_name: 行政编码到中文名的映射字典
    :param output_path: 结果保存的 Excel 文件路径，默认为 None，将根据 folder_path 生成
    """
    # 初始化一个空的DataFrame来存储结果
    if admin_code_to_name is None:
        admin_code_to_name = admin_code_to_name_default

    cost_type_mapping = get_cost_type_mapping(mapping_name)
    # 定义列名
    columns = ['行政区划代码', '核算地区', '面积（km2）', '调节服务项', '生态系统', '实物量总值（t）',
               '实物量地均值（t/km2）','实物量地均值（t/m2）', '价格（元/t）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）']
    results = pd.DataFrame(columns=columns)

    # 遍历文件夹中的所有文件
    for filename in tqdm(os.listdir(folder_path), desc="Processing TIF files"):
        if filename.endswith('.tif'):
            # 提取行政编码
            admin_code = int(filename.split('_')[0])
            # 提取出来的是9位乡镇代码，需要替换成6位省份代码，规则是取9位乡镇代码的前两位，后四位是0000组成
            # 将 9 位乡镇代码转为 6 位省份代码（前两位 + 0000）
            province_code = int(str(admin_code)[:2] + "0000")  # 如 361124100 → 360000
            # print(f"原始乡镇代码: {admin_code}")
            # print(f"转换后省份代码: {province_code}")

            # 提取实物量类型和生态系统类型
            quantity_type = filename.split('_')[1]
            ecosystem_type = filename.split('_')[2]

            # 打开TIF文件
            with rasterio.open(os.path.join(folder_path, filename)) as src:
                # 读取所有波段的数据
                data = src.read(1)
                # todo nodata
                nodata = src.nodata
                data[data == nodata] = np.nan

                # 计算总值和平均值
                Q_total_value = np.nansum(data)  # 忽略NaN值
                # Q_mean_value = np.nanmean(data) / 0.0009 if np.nanmean(data) != 0 else 0  # 忽略NaN值       实物量地均值（t/km2）

                if np.isnan(data).all() or len(data) == 0:
                    Q_mean_value = 0
                else:
                    mean_val = np.nanmean(data)
                    Q_mean_value = mean_val / 0.0009 if mean_val != 0 else 0

                # 使用np.sum()来计算非NaN元素的个数
                area = np.sum(np.logical_not(np.isnan(data))) * 0.0009  # 面积（km2）
                # self_mean_value = Q_total_value / area
                # print(f"np输出的实物量地均值{Q_mean_value}与计算的实物量地均值{self_mean_value}")

                # 该地区的实物量乘以该地区的价格得到价值量 ,根据province_code提取价格
                V_cost = get_excel_value_by_key(excel_path, '行政区划代码', province_code,
                                                cost_type_mapping.get(quantity_type))
                print(f"该地区的{quantity_type}-{cost_type_mapping.get(quantity_type)}为{V_cost}")

                V_total_value = Q_total_value * V_cost
                V_mean_value = V_total_value / area if area != 0 else 0  # 实物量地均值（t/km2），避免除以零错误
                # 将结果添加到DataFrame
                new_row = pd.DataFrame({
                    columns[0]: [admin_code],  # 行政编码
                    columns[1]: [admin_code_to_name.get(str(admin_code), '未知地区')],  # 核算地区
                    columns[2]: [area],  # 面积（km2）

                    columns[3]: [quantity_type],  # 调节服务项
                    columns[4]: [ecosystem_type],  # 生态系统
                    columns[5]: [Q_total_value],  # 实物量总值（t）
                    columns[6]: [Q_mean_value],  # 实物量地均值（t/km2）
                    columns[7]: [Q_mean_value/1e6],  # 实物量地均值（t/m2）
                    columns[8]: [V_cost],  # 价格（元/t）
                    columns[9]: [V_total_value],  # 价值量总值（元）
                    columns[10]: [V_mean_value],  # 价值量地均值（元/km2）
                    columns[11]: [V_mean_value/1e6]  # 价值量地均值（元/m2）
                })
                # 方法一：在 concat 前排除空或全为 NA 的列
                new_row = new_row.dropna(axis=1, how='all')  # 删除全为 NA 的列
                results = pd.concat([results, new_row], ignore_index=True)

    # 根据 folder_path 生成默认的 output_path
    if output_path is None:
        folder_name = os.path.basename(folder_path)
        parent_folder_path = os.path.dirname(folder_path)  # 获取上级文件夹路径
        output_path = os.path.join(parent_folder_path, rf'{folder_name}_results.xlsx')

    # 将结果存储到Excel文件
    # results.to_excel(output_path, index=False)
    # 将DataFrame写入Excel文件
    with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
        results.to_excel(writer, index=False, sheet_name='Sheet1')

        # 获取工作簿和工作表
        workbook = writer.book
        worksheet = writer.sheets['Sheet1']

        # 设置价格1列的单元格格式为货币
        for cell in worksheet['H']:
            cell.number_format = '¥#,##0.00'
        # 设置价格1列的单元格格式为货币
        for cell in worksheet['I']:
            cell.number_format = '¥#,##0.00'
        # 设置价格1列的单元格格式为货币
        for cell in worksheet['J']:
            cell.number_format = '¥#,##0.00'

        # 设置最适应列宽
        for column in worksheet.columns:
            max_length = 0
            column = list(column)
            for cell in column:
                try:  # 需要处理cell.value为None的情况
                    if len(str(cell.value)) > max_length:
                        max_length = len(cell.value)
                except:
                    pass
            adjusted_width = (max_length + 2) * 2
            from openpyxl.utils import get_column_letter
            worksheet.column_dimensions[get_column_letter(column[0].column)].width = adjusted_width

    columns_to_keep_2 = ['实物量总值（t）', '实物量地均值（t/km2）','实物量地均值（t/m2）','价格（元/t）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）','行政区划代码', '核算地区', '面积（km2）', '生态系统']

    if mapping_name == 'ap_cost_type_mapping' :
        columns_to_sum = ['实物量总值（t）', '实物量地均值（t/km2）','实物量地均值（t/m2）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）']
        columns_to_keep = ['行政区划代码', '核算地区', '面积（km2）', '生态系统']
        rows_to_replace = ['QapNOx', 'QapPM', 'QapSO2']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)
    elif mapping_name == 'wp_cost_type_mapping':
        columns_to_sum = ['实物量总值（t）', '实物量地均值（t/km2）','实物量地均值（t/m2）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）']
        columns_to_keep = ['行政区划代码', '核算地区', '面积（km2）', '生态系统']
        rows_to_replace = ['QwpCOD', 'QwpTN', 'QwpTP']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)
    elif mapping_name == 'ett_cost_type_mapping':
        columns_to_sum = ['实物量总值（t）', '实物量地均值（t/km2）','实物量地均值（t/m2）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）', '面积（km2）']
        columns_to_keep = ['行政区划代码', '核算地区', '价格（元/t）','生态系统']
        rows_to_replace = ['Ett', 'Ept', 'Ewe']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)
    elif mapping_name == 'fm_cost_type_mapping':
        columns_to_sum = ['实物量总值（t）', '实物量地均值（t/km2）','实物量地均值（t/m2）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）', '面积（km2）']
        columns_to_keep = ['行政区划代码', '核算地区','价格（元/t）', '生态系统']
        rows_to_replace = ['Cvfm', 'Cmfm', 'Crfm', 'Clfm', 'Cpfm', 'Cwfm']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)
    elif mapping_name == 'tco2_cost_type_mapping':
        columns_to_sum = []
        columns_to_keep = columns_to_keep_2
        rows_to_replace = ['Qtco2']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)
    elif mapping_name == 'wr_cost_type_mapping':
        columns_to_sum = []
        columns_to_keep = columns_to_keep_2
        rows_to_replace = ['Qwr']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)
    elif mapping_name == 'sr_cost_type_mapping':
        columns_to_sum = []
        columns_to_keep = columns_to_keep_2
        rows_to_replace = ['Qsr']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)
    elif mapping_name == 'vsr_cost_type_mapping':
        columns_to_sum = []
        columns_to_keep = ['实物量总值（t）', '实物量地均值（t/km2）','实物量地均值（t/m2）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）','行政区划代码', '核算地区', '面积（km2）', '生态系统']
        rows_to_replace = ['Vsr']
        ap_wp_process_excel_file(output_path, columns_to_sum, columns_to_keep, rows_to_replace)

    print(f'结果已保存到 {output_path}')

import openpyxl
from openpyxl.styles import Font, Alignment, Border, Side
from collections import defaultdict

# columns_to_sum = ['实物量总值（t）', '实物量地均值（t/km2）','实物量地均值（t/m2）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）']
# columns_to_keep = ['行政区划代码', '核算地区', '面积（km2）', '生态系统']

def extract_first_field(value):
    """
    根据大写字母划分字段，提取第一个字段。
    例如：QapNOx -> Qap
    """
    match = re.match(r'[A-Z][^A-Z]*', value)
    return match.group(0) if match else value
def ap_wp_process_excel_file(excel_path, columns_to_sum, columns_to_keep, rows_to_replace):
    """
    处理Excel文件，将指定的三行数据合并为一行，并进行加和和格式设置。

    :param excel_path: Excel文件路径
    :param columns_to_sum: 需要加和的列名列表
    :param columns_to_keep: 需要保留原值的列名列表
    :param rows_to_replace: 需要替换的行标识列表
    """
    # 打开工作簿
    workbook = openpyxl.load_workbook(excel_path)
    sheet = workbook.active  # 假设操作的是第一个工作表

    # 创建一个新的工作表
    if "处理结果" in workbook.sheetnames:
        workbook.remove(workbook["处理结果"])  # 如果已存在，先删除
    new_sheet = workbook.create_sheet(title="处理结果")

    # 获取列索引
    column_indices = {sheet.cell(row=1, column=col).value: col for col in range(1, sheet.max_column + 1)}

    # 确保所有需要的列都在表中
    if not all(col in column_indices for col in columns_to_sum + columns_to_keep):
        raise ValueError("某些列名在表格中不存在，请检查列名是否正确。")

    # 创建一个字典，用于按行政区划代码分组存储数据
    grouped_data = defaultdict(list)

    # 遍历表格，按行政区划代码分组
    for row in range(2, sheet.max_row + 1):  # 假设第一行是表头
        admin_code = sheet.cell(row=row, column=column_indices['行政区划代码']).value
        service_item = sheet.cell(row=row, column=column_indices['调节服务项']).value
        if service_item in rows_to_replace:
            grouped_data[admin_code].append(row)

    # 复制表头到新工作表，并保留格式
    for col in range(1, sheet.max_column + 1):
        new_sheet.cell(row=1, column=col).value = sheet.cell(row=1, column=col).value
        # 复制字体
        new_sheet.cell(row=1, column=col).font = Font(
            name=sheet.cell(row=1, column=col).font.name,
            size=sheet.cell(row=1, column=col).font.size,
            bold=sheet.cell(row=1, column=col).font.bold,
            italic=sheet.cell(row=1, column=col).font.italic,
            underline=sheet.cell(row=1, column=col).font.underline,
            color=sheet.cell(row=1, column=col).font.color
        )
        # 复制对齐方式
        new_sheet.cell(row=1, column=col).alignment = Alignment(
            horizontal=sheet.cell(row=1, column=col).alignment.horizontal,
            vertical=sheet.cell(row=1, column=col).alignment.vertical,
            wrap_text=sheet.cell(row=1, column=col).alignment.wrap_text
        )
        # 复制边框
        new_sheet.cell(row=1, column=col).border = Border(
            left=Side(style=sheet.cell(row=1, column=col).border.left.style),
            right=Side(style=sheet.cell(row=1, column=col).border.right.style),
            top=Side(style=sheet.cell(row=1, column=col).border.top.style),
            bottom=Side(style=sheet.cell(row=1, column=col).border.bottom.style)
        )

    # 处理每个行政区划代码分组，并将结果写入新工作表
    current_row = 2  # 新工作表的起始行
    for admin_code, rows in grouped_data.items():
        # 初始化加和结果
        sum_values = {col: 0 for col in columns_to_sum}
        # 保留原值
        original_values = {col: sheet.cell(row=rows[0], column=column_indices[col]).value for col in columns_to_keep}

        # 遍历该行政区划代码每行，进行加和
        for row in rows:
            for col in columns_to_sum:
                value = sheet.cell(row=row, column=column_indices[col]).value
                if value is not None:
                    sum_values[col] += value

        # 将结果写入新工作表
        new_sheet.cell(row=current_row, column=column_indices['调节服务项']).value = extract_first_field(
            rows_to_replace[0])
        new_sheet.cell(row=current_row, column=column_indices['生态系统']).value = '全部生态系统'
        for col in columns_to_sum:
            new_sheet.cell(row=current_row, column=column_indices[col]).value = sum_values[col]
        for col in columns_to_keep:
            new_sheet.cell(row=current_row, column=column_indices[col]).value = original_values[col]

        # 复制单元格格式
        for col in range(1, sheet.max_column + 1):
            # 复制字体
            new_sheet.cell(row=current_row, column=col).font = Font(
                name=sheet.cell(row=rows[0], column=col).font.name,
                size=sheet.cell(row=rows[0], column=col).font.size,
                bold=sheet.cell(row=rows[0], column=col).font.bold,
                italic=sheet.cell(row=rows[0], column=col).font.italic,
                underline=sheet.cell(row=rows[0], column=col).font.underline,
                color=sheet.cell(row=rows[0], column=col).font.color
            )
            # 复制对齐方式
            new_sheet.cell(row=current_row, column=col).alignment = Alignment(
                horizontal=sheet.cell(row=rows[0], column=col).alignment.horizontal,
                vertical=sheet.cell(row=rows[0], column=col).alignment.vertical,
                wrap_text=sheet.cell(row=rows[0], column=col).alignment.wrap_text
            )
            # 复制边框
            new_sheet.cell(row=current_row, column=col).border = Border(
                left=Side(style=sheet.cell(row=rows[0], column=col).border.left.style),
                right=Side(style=sheet.cell(row=rows[0], column=col).border.right.style),
                top=Side(style=sheet.cell(row=rows[0], column=col).border.top.style),
                bottom=Side(style=sheet.cell(row=rows[0], column=col).border.bottom.style)
            )

        # 设置货币格式
        # currency_columns = ['实物量地均值（t/km2）','实物量地均值（t/m2）', '价值量总值（元）', '价值量地均值（元/km2）','价值量地均值（元/m2）']
        for col_name in columns_to_sum:
            if col_name in column_indices:
                col_index = column_indices[col_name]
                new_sheet.cell(row=current_row, column=col_index).number_format = '¥#,##0.00'

        current_row += 1  # 移动到下一行

    # 自动调整列宽
    from openpyxl.utils import get_column_letter
    for col in range(1, new_sheet.max_column + 1):
        max_length = 0
        column = new_sheet.column_dimensions[openpyxl.utils.get_column_letter(col)]
        for cell in new_sheet[openpyxl.utils.get_column_letter(col)]:
            try:
                if len(str(cell.value)) > max_length:
                    max_length = len(cell.value)
            except:
                pass
        adjusted_width = (max_length + 2) * 2  # 留出一些额外空间
        column.width = adjusted_width

    # 保存修改后的工作簿（直接保存到原文件）
    workbook.save(excel_path)
    print(f"修改完成，结果已保存到原文件 {excel_path} 的 '处理结果' 工作表中")



def get_files_with_code(base_path: str, code: str) -> List[str]:
    """
    获取指定路径下包含指定6位数字代码的文件路径

    参数:
        base_path (str): 基础路径
        code (str): 6位数字的行政区划代码

    返回:
        list: 匹配的文件路径列表
    """
    pattern = re.compile(rf".*{code}.*\.tif$")
    matching_files = []

    try:
        for root, dirs, files in os.walk(base_path):
            for file in files:
                if pattern.match(file):
                    matching_files.append(os.path.join(root, file))
    except Exception as e:
        logging.error(f"Error in get_files_with_code: {e}")

    return matching_files

def transform_path_xian(file_path: str, code: str, sub_code: str) -> str:
    """
    转换文件路径，将指定的字符串替换为新的字符串，并在路径中插入行政区划代码。

    参数:
        file_path (str): 原始文件路径。
        code (str): 行政区划代码，用于插入到路径中。
        sub_code (str): 替换文件名中匹配的行政区划代码。

    返回:
        str: 转换后的路径。
    """
    try:
        new_path = file_path.replace('GEP_result', 'GEP_project')
        pattern = re.compile(r'(\d{6})_')
        match = pattern.search(file_path)
        if match:
            new_path = new_path.replace(match.group(1), sub_code)
        parts = new_path.split('\\')
        parts.insert(2, code)
        new_path = '\\'.join(parts)
    except Exception as e:
        logging.error(f"Error in transform_path_xian: {e}")
        new_path = file_path

    return new_path

def process_gep_data(gep_result_folder:str ,admin_code: str, target_shi_name: Optional[str] = None, target_xian_name: Optional[str] = None):
    """
    处理GEP数据的主函数

    参数:
        admin_code (str): 行政区划代码
        target_shi_name (Optional[str]): 市名
        target_xian_name (Optional[str]): 县名
    """
    # 提取指定区域的Shapefile
    try:
        target_shp_folder = extract_and_save_shapefile(SHAPEFILE_PATH, target_shi_name, target_xian_name)
        logging.info(f"Shapefile extracted for  {target_shi_name}{target_xian_name}")
    except Exception as e:
        logging.error(f"Error in extracting Shapefile: {e}")
        return

    # 获取指定行政区划代码的TIF文件路径
    matching_files = get_files_with_code(gep_result_folder, admin_code)
    logging.info(f"Found {len(matching_files)} matching files for admin code {admin_code}")

    if not matching_files:
        logging.warning(f"No matching files found for admin code {admin_code}")
        return

    # 转换文件路径并裁剪数据
    for file_path in matching_files:
        try:
            transformed_path = transform_path_xian(file_path, admin_code, admin_code)
            logging.info(f"Transformed path: {transformed_path}")
            output_folder = os.path.dirname(transformed_path)
            os.makedirs(output_folder, exist_ok=True)
            # 裁剪TIF数据
            if target_shi_name is not None:
                logging.info(f"Execute the xian_code cropping method")
                tif_mask_by_shapefile(file_path, target_shp_folder, output_folder=output_folder, city_name="xian_code")
            else:
                logging.info(f"Execute the xiang_code cropping method")
                tif_mask_by_shapefile(file_path, target_shp_folder, output_folder=output_folder, city_name="xiang_code")

            logging.info(f"TIF file {file_path} masked and saved to {transformed_path}")

            # 如果需要计算价值量图
            if 'Q' in os.path.basename(file_path) or 'C' in os.path.basename(file_path) or 'E' in os.path.basename(file_path):

                # todo 获取对应的价格
                column_name = '二氧化碳价格（元/t）'  # 示例列名
                cost = get_excel_value_by_key(EXCEL_PATH, '行政区划代码', int(admin_code), column_name)
                if cost is not None:
                    transformed_path_ouput = transformed_path.replace('.tif', '_value.tif')
                    dev_multiply_tif_data_by_factor(transformed_path, transformed_path_ouput,cost)
                    logging.info(f"Value map generated for {transformed_path} with cost {cost}")
                else:
                    logging.warning(f"Cost value not found for admin code {admin_code}")
        except Exception as e:
            logging.error(f"Error processing file {file_path}: {e}")

import glob
from typing import Dict, Any
def combine_excel_files(
    folder_path: str,
    sheet_name: str = 'Sheet1',
    output_file: str = 'combined_file.xlsx',
    include_subdirectories: bool = False
) -> Dict[str, Any]:
    """
    读取指定文件夹中的所有 Excel 文件（.xlsx），合并指定工作表（sheet）内容，
    并保存为一个新的 Excel 文件。

    :param folder_path: 包含 Excel 文件的文件夹路径
    :param sheet_name: 要读取的工作表名称，默认是 'Sheet1'
    :param output_file: 输出文件路径或文件名，默认为 'combined_file.xlsx'
    :param include_subdirectories: 是否包含子目录中的 Excel 文件，默认为 False

    :return: 包含结果信息的字典，例如成功状态、输出文件路径和总行数。
    """

    # 构建搜索模式
    pattern = os.path.join(folder_path, '**', '*.xlsx') if include_subdirectories else os.path.join(folder_path, '*.xlsx')

    # 获取所有 Excel 文件路径
    excel_files = glob.glob(pattern, recursive=include_subdirectories)

    if not excel_files:
        return {
            "success": False,
            "message": f"在路径 {folder_path} 中未找到任何 Excel 文件。",
        }

    # 初始化一个空的 DataFrame 来存储合并数据
    combined_df = pd.DataFrame()

    # 遍历每个 Excel 文件并读取指定工作表
    for file in excel_files:
        try:
            df = pd.read_excel(file, sheet_name=sheet_name)
            combined_df = pd.concat([combined_df, df], ignore_index=True)
        except Exception as e:
            print(f"无法读取文件 {file}：{e}")
            continue

    # 确保输出目录存在
    output_dir = os.path.dirname(output_file)
    if output_dir and not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 保存合并后的数据到新的 Excel 文件
    combined_df.to_excel(output_file, index=False)

    return {
        "success": True,
        "output_file": output_file,
        "total_rows": len(combined_df),
        "message": f"成功合并 {len(excel_files)} 个文件，共 {len(combined_df)} 行数据。"
    }

def get_leaf_folders(root_folder):
    """
    获取某文件夹中所有没有子文件夹的路径列表。

    参数:
        root_folder (str): 根文件夹路径

    返回:
        list: 所有没有子文件夹的路径列表
    """
    leaf_folders = []

    for dirpath, dirs, files in os.walk(root_folder):
        # 如果当前目录下没有子目录，则认为是叶子文件夹
        if not dirs:
            leaf_folders.append(dirpath)

    return leaf_folders

def create_dict_from_leaf_folders(leaf_folders, keywords):
    """
    根据叶子文件夹的名称创建字典。

    参数:
        leaf_folders (list): 叶子文件夹路径列表
        keywords (list): 用于匹配的关键词列表

    返回:
        dict: 匹配关键词的文件夹路径字典
    """
    result_dict = {}

    for folder in leaf_folders:
        # 获取文件夹的最后一部分名称
        folder_name = os.path.basename(folder)
        # 检查是否包含关键词
        for keyword in keywords:
            if keyword.lower() in folder_name.lower():
                # 判断关键词是否以 q 开头
                if keyword.lower().startswith('q'):
                    # 去掉首字母 q 后生成键
                    key = f"{keyword.lower()[1:]}_variables"
                else:
                    # 普通情况
                    key = f"{keyword.lower()}_variables"
                # 添加路径到字典
                result_dict[key] = folder

    return result_dict

def get_cost_type_mapping(mapping_name: str):
    """
    根据映射名称动态获取对应的 cost_type_mapping 对象。

    :param mapping_name: 要获取的 mapping 名称字符串，如 "fm_cost_type_mapping"
    :return: 对应的 mapping 对象 或 None（未找到时）
    """
    from tif_stats import (
        fm_cost_type_mapping,
        ett_cost_type_mapping,
        wr_cost_type_mapping,
        sr_cost_type_mapping,
        vsr_cost_type_mapping,
        sf_cost_type_mapping,
        vsf_cost_type_mapping,
        ap_cost_type_mapping,
        wp_cost_type_mapping,
        tco2_cost_type_mapping,
    )

    # 映射表：定义字符串名到实际对象的对应关系
    mapping_table = {
        "fm_cost_type_mapping": fm_cost_type_mapping,
        "ett_cost_type_mapping": ett_cost_type_mapping,
        "wr_cost_type_mapping": wr_cost_type_mapping,
        "sr_cost_type_mapping": sr_cost_type_mapping,
        "vsr_cost_type_mapping": vsr_cost_type_mapping,
        "sf_cost_type_mapping": sf_cost_type_mapping,
        "vsf_cost_type_mapping": vsf_cost_type_mapping,
        "ap_cost_type_mapping": ap_cost_type_mapping,
        "wp_cost_type_mapping": wp_cost_type_mapping,
        "tco2_cost_type_mapping": tco2_cost_type_mapping,
    }

    # 返回对应的 mapping 对象，如果找不到则返回 None
    return mapping_table.get(mapping_name)


def process_gep_analysis(
    root_folder: str,
    shp_path: str,
    excel_price_path: str =  r'H:\GEP_excel_data\V_price\价格表-总表.xlsx',
    keywords=None
):
    """
    对指定文件夹中的 TIF 文件进行 GEP 分析，并根据行政区划信息生成 Excel 报告。

    :param root_folder: 包含 TIF 输出的根目录路径
    :param keywords: 用于匹配输出文件夹的关键字列表，如 ['Qap', 'Qwp', ...]
    :param shp_path: 存放乡镇行政区划 .shp 文件的路径
    :param excel_price_path: Excel 价格表路径，用于提取价值量
    """

    # 构建行政区划代码映射
    if keywords is None:
        keywords = ['Qap', 'Qwp', 'Qtco2', 'Qfm', 'Qwr', 'Qsr', 'Qett', 'Qsf', 'Vsr', 'Vsf']
    admin_code_to_name = create_admin_code_mapping(shp_path)

    # 获取所有叶子文件夹并构建 output_base_paths
    leaf_folders = get_leaf_folders(root_folder)
    output_base_paths = create_dict_from_leaf_folders(leaf_folders, keywords)

    # 构建 cost_type_mappings
    cost_type_mappings = {
        key: key.split('_')[0] + "_cost_type_mapping"
        for key in output_base_paths.keys()
    }

    # 遍历 mapping 并执行分析
    for key, mapping_name in cost_type_mappings.items():
        if key in output_base_paths:
            print(f"正在分析 {output_base_paths[key]} 文件...", mapping_name)

            analyze_tif_files_xiang(
                folder_path=output_base_paths[key],
                mapping_name=mapping_name,
                admin_code_to_name=admin_code_to_name,
                excel_path=excel_price_path
            )